package com.wwu.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wwu.common.redis.RedisConst;
import com.wwu.common.redis.RedisUtil;
import com.wwu.common.utils.AssertUtil;
import com.wwu.common.utils.PinyinUtils;
import com.wwu.common.web.ResultObj;
import com.wwu.common.web.ResultPage;
import com.wwu.system.entity.SysDict;
import com.wwu.system.mapper.SysDictMapper;
import com.wwu.system.service.ISysDictService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 *  系统字典服务实现类,并记录到缓存中
 * @author 一蓑烟雨
 * @date 2021-10-26
 * @version 1.0.0
 */
@Slf4j
@Service
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements ISysDictService {
    /** 注入运行环境 */
    @Resource
    private RedisUtil redisUtil;

    /**
     * 根据字典编码或类型编码获取字典信息
     * @param dictTypeId  字典类型编码
     * @param dictId  字典编码
     * @return com.wwu.system.entity.SysDict
     * @author 一蓑烟雨
     * @date 2023/7/6 17:04
     */
    @Override
    public SysDict getDictById(String dictTypeId, String dictId) {
        LambdaQueryWrapper<SysDict> wrapper = new LambdaQueryWrapper<>();
        if(StringUtils.hasText(dictTypeId)){
            wrapper.eq(SysDict::getDictTypeId,dictTypeId);
        }
        if(StringUtils.hasText(dictId)){
            wrapper.eq(SysDict::getDictId,dictId);
        }
        return this.getOne(wrapper);
    }

    /**
     * 根据字典编码或名称获取字典
     * @param dictTypeId  字典类型编码
     * @param dictName  字典名称
     * @return com.wwu.system.entity.SysDict
     * @author 一蓑烟雨
     * @date 2023/7/3 20:01
     */
    @Override
    public SysDict getDictByName(String dictTypeId,String dictName) {
        LambdaQueryWrapper<SysDict> wrapper = new LambdaQueryWrapper<>();
        if(StringUtils.hasText(dictTypeId)){
            wrapper.eq(SysDict::getDictTypeId,dictTypeId);
        }
        if(StringUtils.hasText(dictName)){
            wrapper.eq(SysDict::getDictName,dictName);
        }
        return this.getOne(wrapper);
    }

    /**
     * 分页查询系统字典信息
     * @param pageNum  页码
     * @param pageSize  每页数量
     * @param sysDict  字典实体信息
     * @return com.wwu.common.web.ResultPage<com.wwu.system.entity.SysDict>
     * @author 一蓑烟雨
     * @date 2023/7/3 18:08
     */
    @Override
    public ResultPage<SysDict> getDictListPage(Integer pageNum, Integer pageSize, SysDict sysDict) {
        Page<SysDict> page = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<SysDict> wrapper = new LambdaQueryWrapper<>();
        if(StringUtils.hasText(sysDict.getDictName())){
            wrapper.like(SysDict::getDictName,sysDict.getDictName());
        }
        if(null != sysDict.getDictStatus()){
            wrapper.eq(SysDict::getDictStatus,sysDict.getDictStatus());
        }
        if(null != sysDict.getDictTypeId()){
            wrapper.eq(SysDict::getDictTypeId,sysDict.getDictTypeId());
        }
        wrapper.orderByAsc(SysDict::getDictTypeId).orderByAsc(SysDict::getDictSort);
        IPage<SysDict> sysDictPage = this.page(page, wrapper);
        return new ResultPage<>(sysDictPage);
    }

    /**
     * 添加字典信息
     * @param sysDict  字典实体信息
     * @author 一蓑烟雨
     * @date 2023/7/3 18:08
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void saveDict(SysDict sysDict) {
        AssertUtil.isTrue(!StringUtils.hasText(sysDict.getDictId()),"字典编码不能为空");
        SysDict sysDictTemp = this.getDictById(sysDict.getDictTypeId(),sysDict.getDictId());
        AssertUtil.isTrue(null != sysDictTemp,"字典编码已存在");

        AssertUtil.isTrue(!StringUtils.hasText(sysDict.getDictName()),"类型名称不能为空");
        SysDict sysDictTemp1 = this.getDictByName(sysDict.getDictTypeId(),sysDict.getDictName());
        AssertUtil.isTrue(null != sysDictTemp1 && !sysDict.getDictId().equals(sysDictTemp1.getDictId()),"字典名称已存在");

        sysDict.setPy(PinyinUtils.getPinYin(sysDict.getDictName()));
        sysDict.setWb(PinyinUtils.getWuBi(sysDict.getDictName()));
        AssertUtil.isTrue(!(this.save(sysDict)),"字典添加失败！");
        //更新缓存
        this.sysDictCache();
    }

    /**
     * 更新字典信息
     * @param sysDict  字典实体信息
     * @author 一蓑烟雨
     * @date 2023/7/3 18:08
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void updateDict(SysDict sysDict) {
        AssertUtil.isTrue(!StringUtils.hasText(sysDict.getDictId()),"字典编码不能为空");
        SysDict sysDictTemp = this.getDictById(sysDict.getDictTypeId(),sysDict.getDictId());
        AssertUtil.isTrue(null != sysDictTemp && !sysDict.getDictId().equals(sysDictTemp.getDictId()),"字典编码已存在");

        AssertUtil.isTrue(!StringUtils.hasText(sysDict.getDictName()),"类型名称不能为空");
        SysDict sysDictTemp1 = this.getDictByName(sysDict.getDictTypeId(),sysDict.getDictName());
        AssertUtil.isTrue(null != sysDictTemp1 && !sysDict.getDictId().equals(sysDictTemp1.getDictId()),"字典名称已存在");

        LambdaUpdateWrapper<SysDict> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(SysDict::getDictName,sysDict.getDictName())
                .set(SysDict::getPy,PinyinUtils.getPinYin(sysDict.getDictName()))
                .set(SysDict::getWb,PinyinUtils.getWuBi(sysDict.getDictName()))
                .set(SysDict::getOtherCode,sysDict.getOtherCode())
                .set(SysDict::getDictSort,sysDict.getDictSort())
                .set(SysDict::getRemark,sysDict.getRemark())

                .eq(SysDict::getDictTypeId,sysDict.getDictTypeId())
                .eq(SysDict::getDictId,sysDict.getDictId());
        AssertUtil.isTrue(!this.update(wrapper),"字典更新失败！");
        //更新缓存
        this.sysDictCache();
    }

    /**
     * 更新字典状态
     * @param dictId 字典编码
     * @param dictStatus 字典状态
     * @author 一蓑烟雨
     * @date 2023/7/3 18:09
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void updateDictStatus(String dictTypeId, String dictId, Integer dictStatus) {
        AssertUtil.isTrue(!StringUtils.hasText(dictId),"字典编码不能为空");
        AssertUtil.isTrue(ObjectUtils.isEmpty(dictStatus),"字典状态不能为空");

        LambdaUpdateWrapper<SysDict> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(SysDict::getDictStatus,dictStatus)
               .eq(SysDict::getDictTypeId,dictTypeId)
               .eq(SysDict::getDictId,dictId);
        AssertUtil.isTrue(!this.update(wrapper),"字典状态更新失败！");
        //更新缓存
        this.sysDictCache();
    }

    /**
     * 删除字典(逻辑删除)
     * @param dictTypeId 字典类型编码
     * @param dictId 字典编码
     * @author 一蓑烟雨
     * @date 2023/7/20 16:14
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public void deleteDict(String dictTypeId, String dictId) {
        AssertUtil.isTrue(ObjectUtils.isEmpty(dictTypeId),"字典类型编码为空！");
        AssertUtil.isTrue(ObjectUtils.isEmpty(dictId),"请选择删除的记录！");

        LambdaQueryWrapper<SysDict> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDict::getDictTypeId,dictTypeId)
               .eq(SysDict::getDictId,dictId);
        AssertUtil.isTrue(!this.remove(wrapper),"字典删除失败！");
        //更新缓存
        this.sysDictCache();
    }

    /**
     * 根据字典类型编码删除字典明细
     * @param dictTypeIds 字典类型编码
     * @return boolean
     * @author 一蓑烟雨
     * @date 2023/7/6 11:01
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public boolean deleteDictByTypeId(List<String> dictTypeIds) {
        AssertUtil.isTrue(ObjectUtils.isEmpty(dictTypeIds),"字典类型编码不能为空");
        LambdaQueryWrapper<SysDict> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(SysDict::getDictTypeId,dictTypeIds);

        //如果数量大于0则执行删除操作
        if(this.count(wrapper) > 0){
            AssertUtil.isTrue(!this.remove(wrapper),"字典明细删除失败");
            //更新缓存
            this.sysDictCache();
        }
        return true;
    }

    /**
     * 查询字典数据，在项目启动时加载
     * @return com.wwu.common.web.ResultObj
     * @author 一蓑烟雨
     * @date 2023/7/20 16:14
     */
    @Override
    public ResultObj sysDictCache() {
        LambdaQueryWrapper<SysDict> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDict::getDictStatus,0)
                .orderByAsc(SysDict::getDictTypeId)
                .orderByAsc(SysDict::getDictSort);

        List<SysDict> sysDictList = this.list(wrapper);
        //遍历系统字典，存储到缓存中
        if(!ObjectUtils.isEmpty(sysDictList)) {
            HashMap<String, Object> sysDictHashMap = new HashMap<>();
            for (SysDict sysDict : sysDictList) {
                if (ObjectUtils.isEmpty(sysDictHashMap.get(sysDict.getDictTypeId()))) {
                    sysDictHashMap.put(sysDict.getDictTypeId(), new ArrayList<>());
                }
                List<SysDict> dictList = (List<SysDict>) sysDictHashMap.get(sysDict.getDictTypeId());
                dictList.add(sysDict);
                sysDictHashMap.put(sysDict.getDictTypeId(),dictList);
            }
            //将字典信息保存到缓存中
            redisUtil.setValue(RedisConst.Key.SYS_DICT, JSON.toJSONString(sysDictHashMap, JSONWriter.Feature.WriteMapNullValue));
        }

        return ResultObj.success("系统字典缓存更新成功");
    }
}
